function Student(props) { this.name = props.name || 'Unnamed'; }
Student.prototype.hello = function () { alert('Hello, ' + this.name + '!'); }  // 原型对象上添加方法, 是共有方法
function PrimaryStudent(props) { Student.call(this, props); this.grade = props.grade || 1; }  // 调用 Student 构造函数, 绑定 this 变量
// 定义新的构造函数, 并在内部用 call() 调用希望 "继承" 的构造函数, 并绑定this
// 但是, 调用了 Student 构造函数不等于继承了 Student, PrimaryStudent 创建的对象的原型是
// new PrimaryStudent() ----> PrimaryStudent.prototype ----> Object.prototype ----> null
// 必须想办法把原型链修改为
// new PrimaryStudent() ----> PrimaryStudent.prototype ----> Student.prototype ----> Object.prototype ----> null
PrimaryStudent.prototype = Student.prototype;  // 这么干是不行的, PrimaryStudent 和 Student 共享一个原型对象, 那还要定义 PrimaryStudent 干啥

// 使用中间函数 F()
function PrimaryStudent(props) { Student.call(this, props); this.grade = props.grade || 1; }  // PrimaryStudent 构造函数
function F() { }  // 空函数 F()
F.prototype = Student.prototype;  // 把 F 的原型指向 Student.prototype(Student 的原型对象)
PrimaryStudent.prototype = new F();  // 把 PrimaryStudent 的原型指向一个新的 F 对象, F 对象的原型正好指向 Student.prototype:
PrimaryStudent.prototype.constructor = PrimaryStudent;  // 把 PrimaryStudent 原型的构造函数修复为 PrimaryStudent
PrimaryStudent.prototype.getGrade = function () { return this.grade; };  // 继续在 PrimaryStudent 原型 (就是 new F() 对象) 上定义方法
var xiaoming = new PrimaryStudent({ name: '小明', grade: 2 });  // 创建 xiaoming
console.log(xiaoming.name, xiaoming.grade);  // '小明', 2
// 验证原型
console.log(xiaoming.__proto__ === PrimaryStudent.prototype);  // true
console.log(xiaoming.__proto__.__proto__ === Student.prototype);  // true
// 验证继承关系:
console.log(xiaoming instanceof PrimaryStudent);  // true
console.log(xiaoming instanceof Student);  // true

// 封装一下
function inherits(Child, Parent) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
}
function Student(props) { this.name = props.name || 'Unnamed'; }
Student.prototype.hello = function () { alert('Hello, ' + this.name + '!'); }  // 实现子类可以共用的函数, 绑定到 原型对象
function PrimaryStudent(props) { Student.call(this, props); this.grade = props.grade || 1; }
inherits(PrimaryStudent, Student);  // 实现原型继承链
PrimaryStudent.prototype.getGrade = function () { return this.grade; };  // 绑定其他方法到 PrimaryStudent 原型
var xiaoming = new PrimaryStudent({ name: '小明', grade: 2 });  // 创建 xiaoming
console.log(xiaoming.name, xiaoming.grade);  // '小明', 2
